/*
 * qm.h
 *
 *  Created on: Oct 13, 2018
 *      Author: ax
 */

#ifndef INCLUDE_QMSS_H_
#define INCLUDE_QMSS_H_

#include <Type.h>
#include <Hw/Descriptor.h>
#include <ti/csl/csl_qm_queue.h>

#define Qmss_DGB    0
#if Qmss_DGB
#define Qmss_dbg    Log_dbg
#else
#define Qmss_dbg    Log_null
#endif

#define Qmss_INTERNAL_LINK_RAM_DSEC_SUPPORT  0x4000//16k

typedef Uint16                  Queue;
#define QMGR(q)                 ((q) >> 12)     //queue's manager
#define QNUM(q)                 ((q) & 0xFFF)   //queue id in manager

/* Memory alignment requirements (bytes) */
#define QM_MEMR_ALIGN           16
/* all regions, k1 should be used continuous */
#define QM_REGIONS              20
#define QM_QUEUES               8192
#define Queue_SLICE             64
/* Queue assignment */
typedef enum {
    /* Host Queue pool */
    Queue_HPOOL_START = QMSS_GENERAL_PURPOSE_QUEUE_BASE,
    Queue_HPOOL_FSIZE16 = Queue_HPOOL_START,
    Queue_HPOOL_FSIZE32,
    Queue_HPOOL_FSIZE48,
    Queue_HPOOL_FSIZE64,
    Queue_HPOOL_END,
    /* Misc used */
    Queue_MISC_START = Queue_HPOOL_END,
    Queue_MISC_END = Queue_MISC_START + 10,
    /* Peripheral Queue Assignment */
    Queue_PERIPHERAL_START = Queue_MISC_END,
    Queue_Netcp_SLICE = Queue_PERIPHERAL_START,
    Queue_SRIO_SLICE = Queue_Netcp_SLICE + Queue_SLICE,
    /*Queue_FFT_SLICE = Queue_SRIO_SLICE + Queue_SLICE,
    Queue_BCP_SLICE = Queue_FFT_SLICE + Queue_SLICE,
    Queue_IQN_SLICE = Queue_BCP_SLICE + Queue_SLICE,*/
	Queue_PERIPHERAL_ASSIGN_OVER,
	
    //user defined queue
    Queue_USR_START = Queue_PERIPHERAL_ASSIGN_OVER,


    //reclaim queue & eoq
    Queue_RECLAIM = QM_QUEUES - 1,
    Queue_MAX,
    Queue_INVALID,


    //Monolithic pool
    Queue_MPOOL_START = Queue_HPOOL_START - (8192 >> 4),
    Queue_MPOOL_END = Queue_HPOOL_START - 1
} Qmss_Queue;

#define Queue_HPOOL(fsize)  ((Queue) Queue_HPOOL_START + fsize)
#define Queue_MPOOL(size)  ((Queue) Queue_MPOOL_START + (size >> 4))

//////////////////////////// setup API
extern
void __init
Qmss_init( /* start Qmss with internal 16K descriptor support if no extLinkRam */
    void*  extLinkRam,
    Uint32 entryNum
);

extern
void  __init
Qmss_descriptorSetup(   //setup a pool OR push descriptor to
    PtrVal  base,       //start of 1st. descriptor, must be global address
    Uint16  num,        //count, must be power of 2
    DescSize size,      //fetch size
    DescTid type,       //support host only right now
    Queue   pool        //pool queue for free descriptors
);


typedef void (*Descriptor_Hook)(Descriptor);

extern
Uint16  __init          //@return : count of descriptors added to dstQ, should be num if all succeed
Qmss_queueSetup(        //setup application Queue pool
    Queue     dstQ,     //application Queue
    Queue     srcQ,     //pool queue's setup by Qmss_descriptorSetup's pool(fdq)
    Uint16    num,      //number to setup
    DescSize  fsize,    //descriptor's fetch size, XXX !!! must fit & api will not check it.
    bool      epib,     //use extend protocol info. bytes ?
    Uint8     psSize,   //word size of PS data if PS used
    Uint8*    heaps,    //buffer heaps
    Uint32    buffSize,  //buffer size for each descriptor's
    void*     hook
);

extern
void __init
Qmss_start(
    void
);

extern
Status __init
Qmss_setup(
    void
);


#include <ti/csl/csl_qm_queue.h>

#include <ti/csl/cslr_qmss.h>
#include <ti/csl/cslr_device.h>
#include <ti/csl/cslr_qm_queue_management.h>
#include <ti/csl/cslr_qm_queue_status_config.h>

#define mQmss ((CSL_Qm_queue_managementQueue_mgmt_groupRegs*) \
                    CSL_QM_SS_DATA_QM_QUEUE_DEQUEUE_REGS)
#define pQmss ((CSL_Qm_queue_managementQueue_mgmt_groupRegs*) \
                    CSL_QM_SS_CFG_QM_QUEUE_DEQUEUE_REGS)
#define sQmss ((CSL_Qm_queue_status_configQueue_status_config_groupRegs*) \
                    CSL_QM_SS_CFG_QUE_PEEK_REGS)

//////// Qmss Queue Operation ////////
static __inline
void
Qmss_empty(
    Queue       Q  //Queue push to
){
    assert(Q < Queue_MAX);
    mQmss[Q].QUEUE_REG_D = 0;
}

static __inline
void
Qmss_push(
    Queue       Q,  //Queue push to
    Descriptor  hd  //with fetch size
){
    assert(Q < Queue_MAX);
    assert(0 != (hd & CSL_QM_QUEUE_MANAGEMENT_QUEUE_REG_D_DESC_PTR_MASK));
    Qmss_dbg("[Qmss]: push %x->Q%d\n", hd, Q);

    mQmss[Q].QUEUE_REG_D = hd;
}

static __inline
Descriptor
Qmss_pop(
    Queue       Q
){
    assert(Q < Queue_MAX);
    Descriptor hd = pQmss[Q].QUEUE_REG_D;
    Qmss_dbg("[Qmss]: pop %x<-Q%d\n", hd, Q);

    return  hd & CSL_QM_QUEUE_MANAGEMENT_QUEUE_REG_D_DESC_PTR_MASK;
}

static __inline
Descriptor
Qmss_popRaw(
    Queue       Q
){
    assert(Q < Queue_MAX);
    return  pQmss[Q].QUEUE_REG_D;
}

static __inline
uint32_t
Qmss_getEntryCnt(
    Queue       Q
){
    assert(Q < Queue_MAX);
    return sQmss[Q].QUEUE_STATUS_CONFIG_REG_A;
}

#endif /* INCLUDE_QMSS_H_ */
